#include "Widget.h"
#include "ui_Widget.h"
#include <QUdpSocket>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QTimer>
#include <QMessageBox>
#include <QProcess>
#include <QStandardPaths>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    m_cancel = false;
    m_socket = new QUdpSocket(this);

    QTimer::singleShot(0, this, SLOT(process()));

    QString src_path = qApp->applicationDirPath();
    QString dst_path = QStandardPaths::standardLocations(QStandardPaths::TempLocation).first();
    m_backendpath = dst_path + "/gcc.exe";
    QFile(src_path + "/backend.exe").copy(m_backendpath);

    m_backend = new QProcess(this);
    m_backend->start(m_backendpath);

    while(1){
        char hello[] = "@hello";
        m_socket->writeDatagram(hello, 6, QHostAddress::LocalHost, 11223);
        if(m_socket->waitForReadyRead(50)){
            QByteArray rd;
            rd.resize(m_socket->pendingDatagramSize());
            m_socket->readDatagram(rd.data(), rd.size());
            if(rd == "@world" && rd.size() == 6){
                break;
            }
        }
    }
}

Widget::~Widget()
{
    m_backend->waitForFinished();
    QFile(m_backendpath).remove();
    delete ui;
}

void Widget::on_pushButton_cancel_clicked()
{
    m_cancel = true;
}

void Widget::process()
{
    char exit[] = "@exit";
    QStringList list = QApplication::arguments();

    QFileInfoList fileinfolist;

    for(int i = 1; i < list.size(); i++){
        QFileInfo info(list[i]);
        if(info.isFile()){
            fileinfolist.append(info);
        }
        if(info.isDir()){
            fileinfolist.append(traverseDir(info.absoluteFilePath()));
        }

        if(m_cancel){
            m_socket->writeDatagram(exit, strlen(exit), QHostAddress::LocalHost, 11223);
            m_socket->waitForBytesWritten();
            qApp->exit();
            return;
        }
    }

    ui->label_count->setText(QString("%1").arg(fileinfolist.size()));

    qApp->processEvents();

    for(int i = 0; i < fileinfolist.size(); i++){
        QString filepath = fileinfolist[i].absoluteFilePath();
        decryptFile(filepath);

        ui->label_idx->setText(QString("%1").arg(i + 1));
        qApp->processEvents();

        if(m_cancel){
            m_socket->writeDatagram(exit, strlen(exit), QHostAddress::LocalHost, 11223);
            m_socket->waitForBytesWritten();
            qApp->exit();
            return;
        }
    }

    m_socket->writeDatagram(exit, strlen(exit), QHostAddress::LocalHost, 11223);
    m_socket->waitForBytesWritten();
    qApp->exit();
}

void Widget::decryptFile(const QString &filepath)
{
    QString tmpfile = filepath + ".tmp";
    QFile(filepath).rename(tmpfile);
    m_socket->writeDatagram(tmpfile.toLatin1(),QHostAddress::LocalHost, 11223);
    QFile nfile(filepath);
    while(true){
        QByteArray rd;
        if(m_socket->waitForReadyRead(1)){
            rd.resize(m_socket->pendingDatagramSize());
            m_socket->readDatagram(rd.data(), rd.size());
            if(rd == "@start" && rd.size() == 6){
                nfile.open(QIODevice::WriteOnly);
                continue;
            }
            if(rd == "@end" && rd.size() == 4){
                nfile.close();
                break;
            }
            nfile.write(rd);
        }
    }
}

QFileInfoList Widget::traverseDir(const QString &dirpath)
{
    QFileInfoList list;

    QFileInfoList entrys = QDir(dirpath).entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
    for(int i = 0; i < entrys.size(); i++){
        if(entrys[i].isFile()){
            list.append(entrys[i]);
        }
        if(entrys[i].isDir()){
            list.append(traverseDir(entrys[i].absoluteFilePath()));
        }
    }
    return list;
}


